<template>
  <div class="notice-container">
    <h1 class="page-title">公告管理</h1>

    <!-- 顶部操作栏 -->
    <div class="operation-bar">
      <el-button type="primary" @click="handleAdd">
        <el-icon><Plus /></el-icon>
        新增公告
      </el-button>
      <div class="search-area">
        <el-input
          v-model="searchTitle"
          placeholder="输入公告标题搜索"
          class="search-input"
          clearable
          @keyup.enter="handleSearch"
          @clear="handleSearch"
        >
          <template #suffix>
            <el-icon class="search-icon" @click="handleSearch"><Search /></el-icon>
          </template>
        </el-input>
        <el-button type="primary" @click="handleSearch">搜索</el-button>
      </div>
    </div>

    <!-- 批量操作栏 -->
    <div v-if="selectedNotices.length > 0" class="batch-operation-bar">
      <span>已选择 {{ selectedNotices.length }} 项</span>
      <el-button type="danger" @click="handleBatchDelete">批量删除</el-button>
    </div>

    <!-- 公告列表 -->
    <el-table
      :data="notices"
      style="width: 100%; margin-top: 20px"
      v-loading="loading"
      border
      @selection-change="handleSelectionChange"
    >
      <el-table-column type="selection" width="55" />
      <el-table-column prop="id" label="ID" width="80" />
      <el-table-column prop="title" label="公告标题" min-width="150" show-overflow-tooltip />
      <el-table-column prop="publishTime" label="发布时间" width="180" />
      <el-table-column prop="coverImage" label="封面" width="220">
        <template #default="scope">
          <el-image
            v-if="scope.row.coverImage"
            :src="scope.row.coverImage"
            fit="cover"
            style="width: 100%; height: 100px; border-radius: 4px"
          />
          <span v-else class="no-image">无封面</span>
        </template>
      </el-table-column>
      <el-table-column prop="type" label="类型" width="100" align="center">
        <template #default="scope">
          <el-tag :type="scope.row.type === 'link' ? 'primary' : 'success'">
            {{ scope.row.type === 'link' ? '链接' : '手动编辑' }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="内容" min-width="120" show-overflow-tooltip>
        <template #default="scope">
          <el-link
            v-if="scope.row.type === 'link' && scope.row.linkUrl"
            :href="scope.row.linkUrl"
            target="_blank"
            type="primary"
          >
            {{ scope.row.linkUrl }}
          </el-link>
          <div v-else>
            {{ scope.row.content }}
          </div>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="180" fixed="right">
        <template #default="scope">
          <el-button size="small" @click="handleEdit(scope.row)"> 编辑 </el-button>
          <el-button size="small" type="danger" @click="handleDelete(scope.row)"> 删除 </el-button>
        </template>
      </el-table-column>
    </el-table>

    <!-- 分页 -->
    <div class="pagination-container">
      <el-pagination
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="[10, 20, 30, 50, 100]"
        background
        layout="total, sizes, prev, pager, next, jumper"
        :total="totalNotices"
        @current-change="handlePageChange"
        @size-change="handleSizeChange"
      />
    </div>

    <!-- 新增/编辑公告对话框 -->
    <el-dialog
      v-model="dialogVisible"
      :title="isEdit ? '编辑公告' : '新增公告'"
      width="700px"
      :close-on-click-modal="false"
    >
      <el-form ref="noticeFormRef" :model="noticeForm" :rules="formRules" label-position="top">
        <el-form-item label="公告标题" prop="title">
          <el-input v-model="noticeForm.title" placeholder="请输入公告标题"></el-input>
        </el-form-item>

        <el-form-item label="发布时间" prop="publishTime">
          <el-date-picker
            v-model="noticeForm.publishTime"
            type="datetime"
            placeholder="请选择发布时间"
            format="YYYY-MM-DD HH:mm:ss"
            value-format="YYYY-MM-DD HH:mm:ss"
            style="width: 100%"
          />
        </el-form-item>

        <el-form-item label="封面图片">
          <div class="cover-upload-container">
            <el-upload
              :show-file-list="false"
              :before-upload="handleBeforeUpload"
              :http-request="handleUpload"
              accept="image/*"
              class="cover-uploader"
            >
              <div class="upload-area">
                <el-image v-if="noticeForm.coverImage" :src="noticeForm.coverImage" fit="cover" class="cover-preview" />
                <div v-else class="upload-placeholder">
                  <el-icon class="upload-icon" v-loading="uploadLoading">
                    <Upload v-if="!uploadLoading" />
                  </el-icon>
                  <div class="upload-text">点击上传封面图片</div>
                  <div class="upload-tip">支持 jpg、png、gif 格式，大小不超过 5MB</div>
                </div>
              </div>
            </el-upload>
            <div v-if="noticeForm.coverImage" class="upload-actions">
              <el-button size="small" @click="handleRemoveCover">删除封面</el-button>
              <el-button size="small" type="primary" @click="handleReupload">重新上传</el-button>
            </div>
          </div>
        </el-form-item>

        <el-form-item label="文章类型" prop="type">
          <el-radio-group v-model="noticeForm.type">
            <el-radio value="link">链接地址</el-radio>
            <el-radio value="manual">手动编辑</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item v-if="noticeForm.type === 'link'" label="链接地址" prop="linkUrl">
          <el-input v-model="noticeForm.linkUrl" placeholder="请输入公告链接地址"></el-input>
        </el-form-item>

        <el-form-item v-if="noticeForm.type === 'manual'" label="文章内容" prop="content">
          <div style="border: 1px solid #ccc; width: 100%">
            <Toolbar
              style="border-bottom: 1px solid #ccc"
              :editor="editorRef"
              :defaultConfig="toolbarConfig"
              mode="default"
            />
            <Editor
              style="height: 400px; overflow-y: hidden"
              v-model="noticeForm.content"
              :defaultConfig="editorConfig"
              mode="default"
              @onCreated="handleCreated"
            />
          </div>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleSubmitForm">确认</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, shallowRef, onBeforeUnmount } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Search, Upload } from '@element-plus/icons-vue'
import { noticeAPI, uploadAPI } from '@/api'
import '@wangeditor/editor/dist/css/style.css' // 引入 css
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'

// 响应式数据
const loading = ref(false)
const notices = ref([])
const totalNotices = ref(0)
const currentPage = ref(1)
const pageSize = ref(10)
const searchTitle = ref('')
const selectedNotices = ref([])

// 对话框相关
const dialogVisible = ref(false)
const isEdit = ref(false)
const noticeFormRef = ref(null)

// 上传相关
const uploadLoading = ref(false)

// 富文本编辑器相关
const editorRef = shallowRef()

// 工具栏配置
const toolbarConfig = {
  // 可以配置需要的工具栏按钮
}

// 编辑器配置
const editorConfig = {
  placeholder: '请输入文章内容...',
  MENU_CONF: {
    // 配置上传图片
    uploadImage: {
      async customUpload(file, insertFn) {
        try {
          const response = await uploadAPI.uploadFile(file, 'image')
          if (response.code === 200) {
            const src = response.data.url || response.data
            const node = {
              type: 'image',
              src,
              style: { width: '100%', height: 'auto' },
              children: [{ text: '' }],
            }
            editorRef.value.insertNode(node)
            ElMessage.success('图片上传成功')
          } else {
            ElMessage.error(response.message || '图片上传失败')
          }
        } catch (error) {
          console.error('图片上传失败:', error)
          ElMessage.error('图片上传失败')
        }
      },
    },
  },
}

// 编辑器创建回调
const handleCreated = (editor) => {
  editorRef.value = editor
}

// 公告表单数据
const noticeForm = reactive({
  id: null,
  title: '',
  publishTime: '',
  coverImage: '',
  linkUrl: '',
  type: 'link', // 类型：'link' 表示链接地址，'manual' 表示手动编辑
  content: '', // 文章内容，用于手动编辑
})

// 表单验证规则
const formRules = {
  title: [
    { required: true, message: '请输入公告标题', trigger: 'blur' },
    { min: 2, max: 100, message: '标题长度在 2 到 100 个字符', trigger: 'blur' },
  ],
  type: [{ required: true, message: '请选择文章类型', trigger: 'change' }],
  linkUrl: [
    {
      required: false,
      validator: (rule, value, callback) => {
        if (noticeForm.type === 'link' && !value) {
          callback(new Error('请输入公告链接地址'))
        } else {
          callback()
        }
      },
      trigger: 'blur',
    },
  ],
  content: [
    {
      required: false,
      validator: (rule, value, callback) => {
        if (noticeForm.type === 'manual' && !value) {
          callback(new Error('请输入文章内容'))
        } else {
          callback()
        }
      },
      trigger: 'blur',
    },
  ],
  publishTime: [{ required: true, message: '请选择发布时间', trigger: 'change' }],
}

// 获取公告列表
const fetchNotices = async () => {
  loading.value = true
  try {
    const params = {
      page: currentPage.value,
      pageSize: pageSize.value,
    }

    if (searchTitle.value.trim()) {
      params.title = searchTitle.value.trim()
    }

    const response = await noticeAPI.getList(params)

    if (response.code === 200) {
      notices.value = response.data.list || []
      totalNotices.value = response.data.total || 0
    } else {
      ElMessage.error(response.message || '获取公告列表失败')
    }
  } catch (error) {
    console.error('获取公告列表失败:', error)
    ElMessage.error('获取公告列表失败')
  } finally {
    loading.value = false
  }
}

// 搜索公告
const handleSearch = () => {
  currentPage.value = 1
  fetchNotices()
}

// 分页变化
const handlePageChange = (page) => {
  currentPage.value = page
  fetchNotices()
}

// 页大小变化
const handleSizeChange = (size) => {
  pageSize.value = size
  currentPage.value = 1
  fetchNotices()
}

// 新增公告
const handleAdd = () => {
  isEdit.value = false
  resetForm()
  dialogVisible.value = true
}

// 编辑公告
const handleEdit = async (row) => {
  isEdit.value = true
  try {
    const response = await noticeAPI.getById(row.id)
    if (response.code === 200) {
      Object.assign(noticeForm, response.data)
      dialogVisible.value = true
    } else {
      ElMessage.error(response.message || '获取公告详情失败')
    }
  } catch (error) {
    console.error('获取公告详情失败:', error)
    ElMessage.error('获取公告详情失败')
  }
}

// 删除公告
const handleDelete = async (row) => {
  try {
    await ElMessageBox.confirm(`确定要删除公告"${row.title}"吗？`, '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    })

    const response = await noticeAPI.delete(row.id)
    if (response.code === 200) {
      ElMessage.success('删除成功')
      fetchNotices()
    } else {
      ElMessage.error(response.message || '删除失败')
    }
  } catch (error) {
    if (error !== 'cancel') {
      console.error('删除公告失败:', error)
      ElMessage.error('删除失败')
    }
  }
}

// 选择变化
const handleSelectionChange = (selection) => {
  selectedNotices.value = selection
}

// 批量删除
const handleBatchDelete = async () => {
  if (selectedNotices.value.length === 0) {
    ElMessage.warning('请选择要删除的公告')
    return
  }

  try {
    await ElMessageBox.confirm(`确定要删除选中的 ${selectedNotices.value.length} 篇公告吗？`, '批量删除确认', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    })

    const ids = selectedNotices.value.map((item) => item.id)
    const response = await noticeAPI.deleteByIds(ids)

    if (response.code === 200) {
      ElMessage.success('批量删除成功')
      selectedNotices.value = []
      fetchNotices()
    } else {
      ElMessage.error(response.message || '批量删除失败')
    }
  } catch (error) {
    if (error !== 'cancel') {
      console.error('批量删除失败:', error)
      ElMessage.error('批量删除失败')
    }
  }
}

// 提交表单
const handleSubmitForm = async () => {
  if (!noticeFormRef.value) return

  try {
    const valid = await noticeFormRef.value.validate()
    if (!valid) return
    
    // 处理富文本内容中的图片样式问题
    let content = noticeForm.content
    if (content && noticeForm.type === 'manual') {
      // 移除包含图片的 p 标签中的 text-indent 样式
      content = content.replace(
        /<p([^>]*text-indent[^>]*)>(\s*<img[^>]*>[\s\S]*?)<\/p>/gi,
        (match, pAttrs, imgContent) => {
          // 移除 text-indent 样式
          const newPAttrs = pAttrs.replace(/text-indent:\s*[^;]+;?/gi, '')
          return `<p${newPAttrs}>${imgContent}</p>`
        }
      )
      noticeForm.content = content
    }
    
    const response = isEdit.value
      ? await noticeAPI.update(noticeForm.id, noticeForm)
      : await noticeAPI.create(noticeForm)

    if (response.code === 200) {
      ElMessage.success(isEdit.value ? '更新成功' : '新增成功')
      dialogVisible.value = false
      fetchNotices()
    } else {
      ElMessage.error(response.message || `${isEdit.value ? '更新' : '新增'}失败`)
    }
  } catch (error) {
    console.error(`${isEdit.value ? '更新' : '新增'}公告失败:`, error)
    ElMessage.error(`${isEdit.value ? '更新' : '新增'}失败`)
  }
}

// 上传前验证
const handleBeforeUpload = (file) => {
  // 检查文件类型
  const isImage = file.type.startsWith('image/')
  if (!isImage) {
    ElMessage.error('只能上传图片文件!')
    return false
  }

  // 检查文件大小
  const isLt5M = file.size / 1024 / 1024 < 5
  if (!isLt5M) {
    ElMessage.error('上传图片大小不能超过 5MB!')
    return false
  }

  return true
}

// 处理文件上传
const handleUpload = async (options) => {
  const { file } = options

  uploadLoading.value = true
  try {
    const response = await uploadAPI.uploadFile(file, 'image')

    if (response.code === 200) {
      noticeForm.coverImage = response.data.url || response.data
      ElMessage.success('封面上传成功')
    } else {
      ElMessage.error(response.message || '上传失败')
    }
  } catch (error) {
    console.error('上传失败:', error)
    ElMessage.error('上传失败')
  } finally {
    uploadLoading.value = false
  }
}

// 删除封面
const handleRemoveCover = () => {
  noticeForm.coverImage = ''
}

// 重新上传（触发文件选择）
const handleReupload = () => {
  // 通过点击上传组件来重新选择文件
  const uploadElement = document.querySelector('.cover-uploader input[type="file"]')
  if (uploadElement) {
    uploadElement.click()
  }
}

// 重置表单
const resetForm = () => {
  Object.assign(noticeForm, {
    id: null,
    title: '',
    publishTime: '',
    coverImage: '',
    linkUrl: '',
    type: 'link',
    content: '',
  })

  if (noticeFormRef.value) {
    noticeFormRef.value.clearValidate()
  }
}

// 组件挂载时获取数据
onMounted(() => {
  fetchNotices()
})

// 组件卸载时,销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value
  if (editor == null) return
  editor.destroy()
})
</script>

<style scoped>
.notice-container {
  padding: 20px;
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
  height: 100%;
  overflow-y: auto;
}

.page-title {
  font-size: 24px;
  color: #333;
  margin-bottom: 20px;
  font-weight: 600;
}

.operation-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
}

.search-area {
  display: flex;
  align-items: center;
  gap: 10px;
}

.search-input {
  width: 250px;
}

.no-image {
  color: #999;
  font-size: 12px;
}

.search-icon {
  cursor: pointer;
  color: #409eff;
}

.search-icon:hover {
  color: #337ecc;
}

.batch-operation-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 10px;
  padding: 12px 16px;
  background-color: #f5f7fa;
  border-radius: 4px;
  border-left: 4px solid #409eff;
}

.pagination-container {
  display: flex;
  justify-content: flex-end;
  margin-top: 20px;
}

.cover-uploader {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: border-color 0.3s;
}

.cover-uploader:hover {
  border-color: #409eff;
}

.upload-area {
  width: 200px;
  height: 120px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: #fafafa;
}

.cover-preview {
  width: 200px;
  height: 120px;
  border-radius: 6px;
}

.upload-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #8c939d;
}

.upload-icon {
  font-size: 28px;
  color: #8c939d;
  margin-bottom: 8px;
}

.upload-text {
  font-size: 14px;
  color: #606266;
  margin-bottom: 4px;
}

.upload-tip {
  font-size: 12px;
  color: #909399;
  text-align: center;
  line-height: 1.4;
}

.upload-actions {
  margin-top: 10px;
  display: flex;
  gap: 10px;
}
</style>
